Skip to content

ABI minor 8 — the register groupings served as data, not copied three times - #32

Merged
AdaWorldAPI merged 1 commit into
claude/layout-probefrom
claude/carving-as-data
Aug 25, 2026
Merged

ABI minor 8 — the register groupings served as data, not copied three times#32
AdaWorldAPI merged 1 commit into
claude/layout-probefrom
claude/carving-as-data

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Stacked on #30 (minor 7). Base is claude/layout-probe; retarget to main once #30 merges.

The finding

The wire encoding of §14's carving parameter lived in three places — a Rust match, Java's Carving enum, and abi.md's own table. Each was correct. Nothing anywhere would have failed if one had stopped agreeing with the others.

That is not a documentation problem. It is a correctness problem with no falsifier, and its failure mode is silent: a grouping added or reordered upstream re-maps one copy, a sweep then reads the same 12 bytes under the wrong grouping, and returns a plausible number.

The change

One source, two derivations:

  1. the contract owns the SETCascadeShape::ROTATIONS;
  2. kernels::CARVING_ORDER (a const) derives the ENCODING from it by a RULE — group count, descending, never declaration position;
  3. the manifest SERVES the resultcarving_count: u32 + carvings: [u16; 8], packed (groups << 8) | group_bytes.

No new symbol. The manifest already exists so Java can discover the ABI's shape instead of declaring it, and a wire encoding is exactly such a shape. It arrives on the read Java already performs at load.

A variant reorder upstream cannot re-map the wire. A variant added upstream propagates automatically and is caught in the build by the membership test rather than surfacing on someone's data.

CARVING_ORDER is a const and not a LazyLock because the manifest that serves it is const-initialised.

Meaning is declared; encoding is served

Carving.groups() / groupBytes() stay declaredRAILS_6X2 named anything other than 6 × 2 would be a lie in its own name, and the arity IS the constant's identity. Only wire() / ofWire() became lookups into the served table. The one literal encoding left in the build is CarvingTable.PRE_MINOR_8, whose name says it is history rather than the current answer.

A latent defect this made reachable

Java's load gate required the full manifest layout. This is the first growth of the manifest struct, so it would have made every older artifact fail to load outright — in flat contradiction of §2's additive promise, and it would have taken OldAbiCompatTest's whole premise with it.

The gate now requires only the 104-byte base prefix (Layouts.MANIFEST_BASE_BYTES). Later fields are read only when the library's size_of_manifest covers them and its minor is high enough — both, because a manifest claiming a minor it is too short to carry is a broken artifact and reading it would produce plausible garbage.

Gates

  • Rust: 134 lib tests, cargo fmt + clippy -D warnings clean
  • Java: 304 checks (AllTests, was 288 — CarvingTableTest adds 16)
  • OldAbiCompatTest: green against all four historical .sos (minors 1–4)
  • javac -Xlint:all: 10 warnings, unchanged baseline, none new

Disable-runs — each verified red, then green

assertion disable observed
the manifest serves the derived order swap the packed axes the_manifest_serves_exactly_the_derived_carving_order FAILED
the order is strictly descending reverse the sort that test and two others FAILED
membership agrees both ways change one Java constant's arity both directions fired — served-but-unnameable, and named-but-unserved
the load gate is a prefix, not the layout restore the full-layout gate the minor-4 library fails to load outright

Owned mistake

Mid-session I ran git checkout on kernels.rs to undo a disable-run edit and destroyed the uncommitted work in that file. Reconstructed and re-verified (134 tests, same count). Disable-runs are now backed up to a file first and never reverted with git checkout. Recorded in the board entry rather than quietly fixed.

Still open, unchanged

FacetSchema's third reading is still Pair48 rather than the operator-ruled L6 quads — flagged earlier, untouched here.

Docs: abi.md §17 (new), §2 (load-gate prefix + minor-8 history), §14's table regraded descriptive rather than normative, manifest struct listing, header constants. Board: LATEST_STATE.md, PR_ARC_INVENTORY.md, EPIPHANIES.md (E-LGJ-A-CONSTANT-COPIED-THREE-TIMES-HAS-NO-FALSIFIER-1) — all in the same commit.


🤖 Generated with Claude Code

https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv


Generated by Claude Code

…e times

The wire encoding of the §14 `carving` parameter lived in three places:
a Rust `match`, Java's `Carving` enum, and abi.md's own table. Each was
correct. Nothing would have failed if one had stopped agreeing with the
others — and the failure mode is silent: a grouping added or reordered
upstream re-maps one copy, a sweep then reads the same 12 bytes under the
wrong reading, and returns a plausible number.

One source, two derivations:

  1. the contract owns the SET (CascadeShape::ROTATIONS);
  2. kernels::CARVING_ORDER derives the ENCODING from it by a RULE
     (group count, descending — never declaration position), as a const;
  3. the manifest SERVES the result: carving_count + carvings[8], packed
     (groups << 8) | group_bytes.

No new symbol. The manifest already exists so Java can discover the ABI's
shape rather than declare it, and a wire encoding is exactly such a shape.

Java keeps its ARITY and loses its ENCODING: RAILS_6X2 named anything but
6x2 would be a lie in its own name, so groups()/groupBytes() stay
declared, while wire()/ofWire() read the served table. The one literal
encoding left is CarvingTable.PRE_MINOR_8, whose name says it is history.

Also fixes a latent defect the change made reachable: Java's load gate
required the FULL manifest layout, so this — the first growth of the
manifest struct — would have made every older artifact fail to load, in
flat contradiction of §2's additive promise. The gate now requires only
the 104-byte base prefix; later fields are read when size_of_manifest
covers them AND the minor is high enough.

Gates: Rust 134 lib tests, fmt + clippy -D warnings clean; Java 304
checks (was 288); OldAbiCompatTest green against minors 1-4; no new javac
warnings.

Disable-runs, each red-then-green: swapped packed axes fail the serve
test; a reversed sort fails the order test and two others; a mismatched
Java arity fires BOTH membership directions; the restored full-layout
gate makes the minor-4 library fail to load outright.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e1d70330-b7f5-4292-a220-833f0810c1bf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Aug 25, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_ab3dc661-16f8-43a9-877b-d5767284c903)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 25, 2026 15:38
@AdaWorldAPI
AdaWorldAPI merged commit feba97e into claude/layout-probe Aug 25, 2026
2 checks passed
AdaWorldAPI pushed a commit that referenced this pull request Aug 27, 2026
PR_ARC_INVENTORY had entries for #1-#12, #14, #16, #18, #20 and #32, and
nothing else. Missing: #13, #22-#31, #33-#41 — twenty PRs. (#15/#17/#19/#21
are also absent and correctly so: each is itself an arc-entry-only PR,
exempt under the termination clause.) #32's own entry still read
"(draft, opened …)" with no merge sha.

Corrects this branch's first count, which said nineteen and read the gap as
starting at #21. Both were wrong — it is twenty, and it starts at #13. The
first count was a range subtraction over a file with holes; the enumeration
is what found the difference.

Method, which is the point rather than an aside: each entry drafted from
that PR's own body and diff, five parallel agents over four PRs each, none
permitted to work from a later session's recall. Every backfilled entry's
Confidence bullet ends "Backfilled 2026-08-27 from the PR body and diff,
not written at merge time", so reconstructed entries are distinguishable
from ones written at merge time; several state which claims are the PR
body's own and were not re-verified. Every cited sha, date and merge-vs-
squash label machine-checked against git.

Four things the backfill turned up, each recorded in the entry it belongs
to: #25's body asserts "no code, no reproducer changes" and its own diff
contradicts it; #39 left its lgj_hop doc comment describing the pre-change
design; #34's banked evidence file did not identify its own JDK; and #41 is
on main while its own title reads [DO NOT MERGE AS-IS], recorded as
unresolved disposition rather than an endorsement.

ISS-LGJ-ARC-INVENTORY-STOPPED-AT-32 moves to RESOLVED with the corrected
count and the standing rule restated: the entry goes in at open, in the
PR's own commit. The backfill is the repair, not the process.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCfrD5y19cvFc4AoyydXYv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants